/**
 * 
 */
package io.gitee.falllee.dao.core;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import com.google.common.cache.Cache;

import io.gitee.falllee.common.util.LogUtils;
import io.gitee.falllee.dao.model.BaseDaoConfig;
import io.gitee.falllee.dao.model.DaoConst;
import io.gitee.falllee.dao.util.CommonUtils;
import io.gitee.falllee.dao.util.DaoUtils;

/**
 * @author batty
 * @date 2022-06-28
 *
 */
public class HeaderBuilder extends BaseBuilder {

    protected Map<String, String> headerParamsMap;
    
    private Cache<String, Optional<Object>> userCache = com.google.common.cache.CacheBuilder.newBuilder()
            .expireAfterWrite(5, TimeUnit.MINUTES).build();
    
    protected HeaderBuilder(BaseDaoConfig daoConfig) {
        super(daoConfig);
    }

    protected Map<String, String> getHeaderParamsMap() {
        Map<String, String> map = CommonUtils.getHeaderParam(daoConfig);
        if (ObjectUtils.isEmpty(headerParamsMap)) {
            return map;
        }
        map.putAll(headerParamsMap);
        return map;
    }

    /**
     * 获取当前用户
     * 
     * @return
     */
    protected Object getCurrentUser() {
        // 从缓存读取
        String empNo = CommonUtils.getUserId(getHeaderParamsMap(), daoConfig);
        // 如果请求头无法获取人员相关信息，直接调用DAO配置类的接口
        if (!StringUtils.hasLength(empNo)) {
            return daoConfig.getCurrentUser();
        }
        try {
            return userCache.get(empNo, new Callable<Optional<Object>>() {

                @Override
                public Optional<Object> call() throws Exception {
                    Object obj = daoConfig.getCurrentUser();
                    return Optional.ofNullable(obj);
                }

            }).orElse(null);
        } catch (Exception e) {
            LogUtils.logException(e);
            return null;
        }
    }
    
    protected Map<String, Object> getFixedFieldValue() {
        Map<String, Object> map = new HashMap<>();
        String headerParamKey = daoConfig.getHeaderParamKey();
        if (!StringUtils.hasLength(headerParamKey)) {
            return map;
        }
        Map<String, String> headerMap = getHeaderParamsMap();
        String[] headerParamKeyArr = DaoUtils.getFixHeaderParamKey(headerParamKey);
        Map<String, String> keyColumnMap = DaoUtils.getFixHeaderParamKeyColumnMap(headerParamKey);
        // 按,分割，支持多个key
        for (String key : headerParamKeyArr) {
            map.computeIfAbsent(keyColumnMap.get(key), p -> CommonUtils.getValueIgnoreCase(headerMap, key));
        }
        return map;
    }

    protected List<String> listFixField() {
        Map<String, Object> fixFieldValue = getFixedFieldValue();
        return fixFieldValue.keySet().stream().map(String::toLowerCase)
                .collect(Collectors.toList());
    }
    
    /**
     * 设置创建人
     * 
     * @param map             参数
     */
    protected void setCreateInfo(Map<String, Object> map) {
        String createUserFieldName = daoConfig.getCreateUser();
        if (StringUtils.hasLength(createUserFieldName)) {
            Object userId = getCurrentUser();
            map.put(DaoConst.CREATE_USER, getQuoteField(createUserFieldName));
            map.put(DaoConst.CREATE_USER_VALUE, userId);
        }
        String createDateFieldName = daoConfig.getCreateDate();
        if (StringUtils.hasLength(createDateFieldName)) {
            map.put(DaoConst.CREATE_DATE, getQuoteField(createDateFieldName));
        }
    }

    /**
     * 设置更新人
     * 
     * @param map             参数
     */
    protected void setUpdateInfo(Map<String, Object> map) {
        String updateUserFieldName = daoConfig.getUpdateUser();
        if (StringUtils.hasLength(updateUserFieldName)) {
            Object userId = getCurrentUser();
            map.put(DaoConst.UPDATE_USER, getQuoteField(updateUserFieldName));
            map.put(DaoConst.UPDATE_USER_VALUE, userId);
        }
        String updateDateFieldName = daoConfig.getUpdateDate();
        if (StringUtils.hasLength(updateDateFieldName)) {
            map.put(DaoConst.UPDATE_DATE, getQuoteField(updateDateFieldName));
        }
    }

}
